package com.example.demo.serviceimpl;

import com.example.demo.entity.BankAccountEntity;
import com.example.demo.repository.BankAccountRepository;
import com.example.demo.service.BankAccountService;
import com.example.demo.util.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author xzy
 * @date 2020-11-13 10:16
 * 说明：
 */
@Service("transactionTemplateImpl")
public class BankAccountServiceTransactionTemplateImpl implements BankAccountService {

    private final TransactionTemplate transactionTemplate;
    private static final String NOT_DELETE = "0";
    private final BankAccountRepository bankAccountRepository;

    @Autowired
    public BankAccountServiceTransactionTemplateImpl(PlatformTransactionManager platformTransactionManager,
                                                     BankAccountRepository bankAccountRepository) {
        this.transactionTemplate = new TransactionTemplate(platformTransactionManager);
        this.bankAccountRepository = bankAccountRepository;
    }

    /**
     * 新增一条银行账户数据
     *
     * @param newBankAccountRecord - 新增的银行账户数据
     * @return - 实际保存到数据库中的数据
     * @throws IllegalArgumentException - 账号已经被使用
     */
    @Override
    public BankAccountEntity save(BankAccountEntity newBankAccountRecord) {
        return null;
    }

    /**
     * 转账
     *
     * @param from  - 原始账户
     * @param to    - 目标账户
     * @param money - 转账金额
     * @return - 操作接口
     */
    @Override
    public Message transfer(String from, String to, BigDecimal money) {
        BankAccountEntity fromAccount;
        BankAccountEntity toAccount;

        // 1.验证账号是否存在
        try {
            fromAccount = bankAccountExistenceCheck(from);
            toAccount = bankAccountExistenceCheck(to);
        } catch (IllegalArgumentException i) {
            return Message.fail("转账失败！错误原因：" + i.getMessage());
        }

        // 2.验证余额是否充足
        if (fromAccount.getBalance().compareTo(money) < 0) {
            return Message.fail("转账失败！错误原因：账户余额不足。");
        }

        // 3.修改账户余额
        return this.transactionTemplate.execute(new TransactionCallback<Message>() {
            @Override
            public Message doInTransaction(TransactionStatus status) {
                try {
                    fromAccount.setBalance(fromAccount.getBalance().subtract(money));
                    toAccount.setBalance(toAccount.getBalance().add(money));
                    bankAccountRepository.saveAndFlush(fromAccount);

                    // 手动抛出一个异常，测试事务管理的有效性
                    if (money.compareTo(new BigDecimal(2000)) == 0) {
                        throw new UnsupportedOperationException();
                    }

                    bankAccountRepository.saveAndFlush(toAccount);
                } catch (Exception e) {
                    e.printStackTrace();
                    status.setRollbackOnly();
                    return Message.fail("修改账户余额失败！");
                }

                return Message.ok("转账成功");
            }
        });
    }

    /**
     * 银行账号存在性检查
     *
     * @param account - 待检查的账号
     * @return - 若账号存在，且数据正常，返回账号对应的账户信息。
     * @throws IllegalArgumentException - 账号不存在、账号重复
     */
    private BankAccountEntity bankAccountExistenceCheck(String account) {

        List<BankAccountEntity> bankAccountList = bankAccountRepository.findAllByAccountAndDeleteFlag(account, NOT_DELETE);
        if (bankAccountList.isEmpty()) {
            throw new IllegalArgumentException("账号" + account + "不存在！");
        }
        if (bankAccountList.size() > 1) {
            throw new IllegalArgumentException("数据库异常，请联系管理员进行处理！");
        }
        return bankAccountList.get(0);
    }
}
